package gu.sql2java.wherehelper;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Strings.isNullOrEmpty;
import static com.google.common.base.Strings.nullToEmpty;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.io.Resources;

import gu.sql2java.BaseBean;
import gu.sql2java.BaseRow;
import gu.sql2java.SimpleLog;
import gu.sql2java.wherehelper.annotations.EnableWhereHelper;
import gu.sql2java.wherehelper.annotations.Equal;
import gu.sql2java.wherehelper.annotations.EqualIf;
import gu.sql2java.wherehelper.annotations.Expression;
import gu.sql2java.wherehelper.annotations.GroupBy;
import gu.sql2java.wherehelper.annotations.IfElse;
import gu.sql2java.wherehelper.annotations.OrderBy;


/**
 * 基于调用者提供的表达式生成动态执行脚本(BeanShell)
 * @author guyadong
 *
 */
public class BeanShellWhereBuilder{
	/*****************************************/
	/** 脚本模板名称定义                         **/
	/*****************************************/	
	private static final String TMPL_EQUAL = "equal.tmpl";
	private static final String TMPL_EQUAL_IF = "equal_if.tmpl";
	private static final String TMPL_IF_ELSE = "if_else.tmpl";
	private static final String TMPL_GROUP_BY = "group_by.tmpl";
	private static final String TMPL_ORDER_BY = "order_by.tmpl";
	private static final String TMPL_EXP = "exp.tmpl";
	private static final String TMPL_LIMIT = "limit.tmpl";
	private static final String TMPL_BEFORE_COND = "before_cond.tmpl";
	private static final String TMPL_AFTER_COND = "after_cond.tmpl";
	private static final String NO_FIRST_CONDITION = "$<NO_FIRST_CONDITION>";
    public static final String NOT_EQUAL = "$<NOT_EQUAL>";
    public static final String IGNORE_EMPTY = "$<IGNORE_EMPTY>";
	private static final String AND_OR = "$<AND_OR>";
	private static final String DEFAULT_ORDER_BY_VAR = "order_by_column";
	private static final String DEFAULT_GROUP_BY_VAR = "group_by_column";
	public static final String KEYWORD_COND_COUNT = "cond_count";
	public static final String KEYWORD_WHERE_BUFFER = "where_buffer";
	public static final String KEYWORD_EXP_BUFFER = "cond_buffer";
	public static final String DT_MYSQL="MySQL";
	private static class Tmpls{		
		/**
		 * 模板名-动态脚本模板内容映射
		 */
		private final static ImmutableMap<String, String> tmpls = loadAllTemplates();
	}
	private String selectFrom = "";
	private String andor = "AND";
	/**
	 * 所有imoprt导入语句
	 */
	private List<String> importLines = Lists.newLinkedList();
	/**
	 * 所有表达式的bsh脚本
	 */
	private List<String> conditionCodes = Lists.newLinkedList();
	private List<String> orderByColumns = Lists.newLinkedList();
	private List<String> groupByColumns = Lists.newLinkedList();
	/**
	 * SQL 类型,目前只支持MySQL
	 */
	private String sqltype = DT_MYSQL;
	/**
	 * 是否输出调试日志
	 */
	private boolean debuglog = false;
	/**
	 * 是否生成分页查询语句
	 */
	private boolean pagequery = true;
	/**
	 * 输入参数的目标表对象,默认为 {@link BaseBean}
	 */
	private Class<? extends BaseRow> targetClass = BaseRow.class;
	/**
	 * 引用变量名列表
	 */
	private Set<String> referenceVariables;
	/**
	 * 变量字段名对应的类型映射
	 */
	private Map<String, Class<?>> varTypes = Collections.emptyMap();
	private String orderByVarname = DEFAULT_ORDER_BY_VAR;
	private String groupByVarname = DEFAULT_GROUP_BY_VAR;
	BeanShellWhereBuilder(){
	}
	
	public boolean debuglog() {
		return debuglog;
	}

	/**
	 * 设置是否输出调试信息
	 * @param debuglog
	 * @return 当前对象
	 */
	public BeanShellWhereBuilder debuglog(boolean debuglog) {
		this.debuglog = debuglog;
		return this;
	}

	/**
	 * 设置是否支持生成分页查询语句(如MySQL LIMIT ${row_count}  OFFSET ${offset})
	 * @param pagequery
	 * @return 当前对象
	 */
	public BeanShellWhereBuilder pagequery(boolean pagequery){
		this.pagequery = pagequery;
		return this;
	}
	public Set<String> getReferenceVariables() {
		return referenceVariables;
	}

	public Class<? extends BaseRow> getTargetClass() {
		return targetClass;
	}

	public Map<String, Class<?>> getVarTypes() {
		return varTypes;
	}

	/**
	 * @return orderByVarname
	 */
	public String getOrderByVarname() {
		return orderByVarname;
	}

	/**
	 * @return groupByVarname
	 */
	public String getGroupByVarname() {
		return groupByVarname;
	}

	/**
	 * @return orderByColumns
	 */
	public String getOrderByColumns() {
		return Joiner.on(',').join(orderByColumns);
	}

	/**
	 * @return groupByColumns
	 */
	public String getGroupByColumns() {
		return Joiner.on(',').join(groupByColumns);
	}

	/**
	 * 生成一般表达式
	 * @param exp
	 * @return 当前对象
	 */
	public BeanShellWhereBuilder exp(String exp){
		exp = nullToEmpty(exp).trim();
		if(!isNullOrEmpty(exp)) {
			conditionCodes.add(Tmpls.tmpls.get(TMPL_EXP)
					.replace(NO_FIRST_CONDITION, ""+!conditionCodes.isEmpty())
					.replace(AND_OR, andor)
					.replace("$<exp>", exp)	);
		}
		return this;
	}
	/**
	 * 指定与前一个表达式的连接方式为OR
	 * @return 当前对象
	 */
	public BeanShellWhereBuilder or(){
		andor = "OR";
		return this;
	}
	/**
	 * 指定与前一个表达式的连接方式为AND
	 * @return 当前对象
	 */
	public BeanShellWhereBuilder and(){
		andor = "AND";
		return this;
	}
	/**
	 * 参见{@link #equal(String)},不之处在于如果column_name为{@code null}或空则忽略,不生成表达式
	 * @param left 
	 * @param field
	 * @param not 为{@code true}执行不等价比较
	 * @param notCheckEmpty 为{@code true} 不检查字段是否为{@code null}或空
	 * @return 当前对象
	 */
	private BeanShellWhereBuilder equal(String left,String field, boolean not, boolean notCheckEmpty){
		if(!isNullOrEmpty(field)) {
			conditionCodes.add(Tmpls.tmpls.get(TMPL_EQUAL)
					.replace(NO_FIRST_CONDITION, ""+!conditionCodes.isEmpty())
					.replace(NOT_EQUAL, "" + not)
					.replace(IGNORE_EMPTY, "" + notCheckEmpty)
					.replace(AND_OR, andor)
					.replace("$<field>", field)
					.replace("$<left>", !isNullOrEmpty(left)? left: field));
		}
		return this;
	}

	/**
	 * 创建一个等价表达式，如{@code  column_name = $<column_name>},<br>
	 * 如果column_name为{@code null}或空,则表达式为 {@code  column_name IS NULL}<br>
	 * 如果column_name为集合,则为IN表达式 {@code  column_name IN (...)}<br>
	 * @param field
	 * @return 当前对象
	 */
	public BeanShellWhereBuilder equal(String field){
		return equal(null,field,false, true);
	}
	/**
	 * @param left
	 * @param field
	 * @return
	 * @since 3.17.5
	 */
	public BeanShellWhereBuilder equal(String left, String field){
	    return equal(left,field,false, true);
	}
	/**
	 * 创建一个不等价表达式，如{@code  column_name != $<column_name>},<br>
	 * 如果column_name为{@code null}或空,则表达式为 {@code  column_name IS NOT NULL}<br>
	 * 如果column_name为集合,则为IN表达式 {@code  column_name NOT IN (...)}<br>
	 * @param field
	 * @return 当前对象
	 */
	public BeanShellWhereBuilder equalNot(String field){
		return equal(null,field,true, true);
	}
	public BeanShellWhereBuilder equalNot(String left,String field){
	    return equal(left,field,true, true);
	}
	/**
	 * 参见{@link #equal(String)},不之处在于如果column_name为{@code null}或空则忽略,不生成表达式
	 * @param field
	 * @param not 为{@code true}执行不等价比较
	 * @return 当前对象
	 */
	public BeanShellWhereBuilder equalIfNonEmpty(String field, boolean not){
		return equal(null,field,not, false);
	}
	/**
	 * @param left
	 * @param field
	 * @param not
	 * @return
	 * @since 3.17.5
	 */
	public BeanShellWhereBuilder equalIfNonEmpty(String left, String field, boolean not){
	    return equal(left,field,not, false);
	}
	/**
	 * 参见{@link #equal(String)},不之处在于如果column_name为{@code null}或空则忽略,不生成表达式
	 * @param field
	 * @return 当前对象
	 */
	public BeanShellWhereBuilder equalIfNonEmpty(String field){
		return equal(null,field,false, false);
	}
	/**
	 * @param left
	 * @param field
	 * @return
	 * @since 3.17.5
	 */
	public BeanShellWhereBuilder equalIfNonEmpty(String left,String field){
	    return equal(left,field,false, false);
	}
	/**
	 * 当满足{@code test}指定的条件时,创建一个等价表达式<br>
	 * 输入参数为{@code null}或空则忽略,不生成表达式
	 * @param test 判断条件
	 * @param field
	 * @param not 为{@code true}执行不等价比较
	 * @return 当前对象
	 * @see #equal(String)
	 */
	public BeanShellWhereBuilder equalIf(String test,String field,boolean not){
		return equalIf(test,field,field,not);
	}
	/**
	 * 当满足{@code test}指定的条件时,创建一个等价表达式<br>
	 * 输入参数为{@code null}或空则忽略,不生成表达式
	 * @param test 判断条件
	 * @param left 
	 * @param field
	 * @param not 为{@code true}执行不等价比较
	 * @return 当前对象
	 * @see #equal(String)
	 * @since 3.17.5
	 */
	public BeanShellWhereBuilder equalIf(String test,String left,String field,boolean not){
	    if(!isNullOrEmpty(test) && !isNullOrEmpty(field)) {
	        conditionCodes.add(Tmpls.tmpls.get(TMPL_EQUAL_IF)
	                .replace(NOT_EQUAL, "" + not)
	                .replace(AND_OR, andor)
	                .replace("$<TEST>", test)
	                .replace("$<field>", field)
	                .replace("$<left>", !isNullOrEmpty(left) ? left : field));
	    }
	    return this;
	}
	/**
	 * 输入条件{@code test}为{@code true}则生成{@code doStatement}指定的表达式,
	 * 否则生成{@code elseStatement}指定的表达式,{@code elseStatement}为{@code null}时不生成表达式
	 * @param test 判断条件
	 * @param doStatement 判断条件为真时的执行语句
	 * @param elseStatement 判断条件为假时的执行语句,为{@code null}忽略
	 * @return 当前对象
	 */
	public BeanShellWhereBuilder ifelse(String test,String doStatement,String elseStatement){
		if(!isNullOrEmpty(test) && !isNullOrEmpty(doStatement)) {
			elseStatement = nullToEmpty(elseStatement);
			conditionCodes.add(Tmpls.tmpls.get(TMPL_IF_ELSE)
					.replace(NO_FIRST_CONDITION, ""+!conditionCodes.isEmpty())
					.replace(AND_OR, andor)
					.replace("$<TEST>", test)
					.replace("$<THEN>", doStatement)
					.replace("$<ELSE>", elseStatement));
		}
		return this;
	}
	/**
	 * 同{@link #ifelse(String, String, String)},只是没有{@code elseStatement}
	 * @param test 判断条件
	 * @param doStatement 判断条件为真时的执行语句
	 * @return 当前对象
	 */
	public BeanShellWhereBuilder onlyif(String test,String doStatement){
		return ifelse(test, doStatement, null);
	}
	/**
	 * 指定SELECT .... FROM 语句,如果不指定，则只生成 WHERE ....部分语句
	 * @param selectFrom select 语句(不含 WHERE部分),为{@code null}忽略
	 * @return 当前对象
	 */
	public BeanShellWhereBuilder selectFrom(String selectFrom) {
		if(!isNullOrEmpty(selectFrom)) {
			this.selectFrom = selectFrom;
		}
		return this;
	}
	/**
	 * 指定ORDER BY 的字段名
	 * @param columnName order by 字段名
	 * @param desc 排序方式,为{@code true}降序
	 * @return 当前对象
	 */
	public BeanShellWhereBuilder orderBy(String columnName,boolean desc) {
		columnName = nullToEmpty(columnName).trim();
		if(!isNullOrEmpty(columnName)) {			
			checkArgument(columnName.matches("('\\w+'|\\w+)"));
			orderByColumns.add(columnName +(desc?" DESC ": ""));
		}
		return this;
	}
	/**
	 * 指定ORDER BY 的字段名,格式要求 ${字段名}[ DESC|ASC]
	 * @param columnName order by 字段名,为{@code null}或空忽略
	 * @return 当前对象
	 */
	public BeanShellWhereBuilder orderBy(String columnName) {
		if(!isNullOrEmpty(columnName)){
			orderByColumns.add(validOrderBy(columnName));
		}
		return this;
	}
	/**
	 * 指定ORDER BY 的字段变量名
	 * @param varName order by 字段字段名,为{@code null}或空忽略
	 * @return 当前对象
	 */
	public BeanShellWhereBuilder orderByVar(String varName) {
		if(!isNullOrEmpty(varName)){
			varName = varName.trim();
			// 必须是以字母开头的只包含数字字母下划线的字符串
			checkArgument(varName.matches("^[_a-zA-Z]\\w*$"),"INVALID variable name [%s]",varName);
			this.orderByVarname = varName; 
		}
		return this;
	}

	/**
	 * 指定GROUP BY 的字段名
	 * @param columnNames group by 字段名列表,为{@code null}忽略
	 * @return 当前对象
	 */
	public BeanShellWhereBuilder groupBy(String ...columnNames) {
		if(null != columnNames){
			Iterable<String> normalized = Iterables.transform(Arrays.asList(columnNames), s->nullToEmpty(s).trim());
			Iterables.addAll(groupByColumns, 
					Iterables.filter(normalized, s->!s.isEmpty() && s.matches("\\w+")));
		}
		return this;
	}
	/**
	 * 指定GROUP BY 的字段变量名
	 * @param varName group by 字段变量名,为{@code null}或空忽略
	 * @return 当前对象
	 */
	public BeanShellWhereBuilder groupByVar(String varName) {
		if(!isNullOrEmpty(varName)){
			varName = varName.trim();
			// 必须是以字母开头的只包含数字字母下划线的字符串
			checkArgument(varName.matches("$[[:alpha:]]\\w?"));
			this.groupByVarname = varName; 
		}
		return this;
	}
	/**
	 * 增加import类型语句，每一个元素为一行导入语句，为{@code null}或空忽略。
	 * 如: {@code import xxx..xxx.ClassA;} 或只提供导入类全名 {@code xxx..xxx.ClassA}
	 * @param imports
	 * @return 当前对象
	 */
	public BeanShellWhereBuilder imports(String ...imports){
		if(null != imports){
			return withImports(Arrays.asList(imports));
		}
		return this;
	}
	/**
	 * 增加import类型语句，每一个元素为一行导入语句，为{@code null}或空忽略。
	 * 如: {@code import xxx..xxx.ClassA;}或只提供导入类全名 {@code xxx..xxx.ClassA}
	 * @param imports
	 * @return 当前对象
	 */
	public BeanShellWhereBuilder withImports(Iterable<String> imports){
		if(null != imports){
			Iterable<String> trans = Iterables.transform(imports, imp->{
				imp = nullToEmpty(imp).trim();
				if(!imp.isEmpty()){
					if(!imp.startsWith("import")){
						imp = "import " + imp;
					}
					if(!imp.endsWith(";")){
						imp = imp + ";";
					}
					imp = imp.replace('$', '.');
				}
				return imp;
			});
			Iterables.addAll(importLines,trans);
		}
		return this;
	}
	/**
	 * 从注解中创建表达式
	 * @param annots
	 * @return 当前对象
	 */
	public BeanShellWhereBuilder from(Annotation[] annots){
		if(null != annots){
			for(Annotation a:annots){
				if(a.annotationType() == EnableWhereHelper.class){
					EnableWhereHelper enableWhereHelper = (EnableWhereHelper)a;
					selectFrom = enableWhereHelper.value();
					debuglog = enableWhereHelper.debuglog();
					andor = validLogicOperator(enableWhereHelper.logicOperator());
					targetClass  = enableWhereHelper.targetClass();
					buildVarTypes(enableWhereHelper);
				}else if(a.annotationType() == Equal.class ){
					Equal eq = (Equal)a;
					equal(eq.left(),eq.value(),eq.not(), eq.notCheckEmpty());
				}else if(a.annotationType() == EqualIf.class ){
					EqualIf eq = (EqualIf)a;
					equalIf(eq.test(), eq.left(), eq.field(),eq.not());
				}else if(a.annotationType() == Expression.class ){
					Expression exp = (Expression)a;
					exp(exp.value());
				}else if(a.annotationType() == IfElse.class){
					IfElse ifElse = (IfElse)a;
					ifelse(ifElse.test(), ifElse.doStatement(), ifElse.elseStatement());
				} else if (a.annotationType() == OrderBy.class) {
					OrderBy orderBy = (OrderBy)a;
					String[] orderBys = orderBy.value();
					for(String o: orderBys){
						orderBy(o);
					}
					orderByVar(orderBy.orderByVarname());
				} else if (a.annotationType() == GroupBy.class) {
					groupBy(((GroupBy)a).value());
				} else {
					try {
						Method method = a.annotationType().getMethod("value");
						Class<?> returnType = method.getReturnType();
						if(returnType.isArray() && Annotation.class.isAssignableFrom(returnType.getComponentType()) ){
							// 递归
							from((Annotation[])method.invoke(a));
						}
					} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
					}
				}
			}
		}
		return this;
	}
	/**
	 * 根据指定的条件生成BeanShell脚本
	 * @return BeanShell脚本字符串
	 */
	String buildScript() {
		//checkState(!conditionCodes.isEmpty(),"must define condition statement");
		conditionCodes.add(Tmpls.tmpls.get(TMPL_ORDER_BY)
				.replace("${"+DEFAULT_ORDER_BY_VAR+"}", "${"+orderByVarname+"}"));
		conditionCodes.add(Tmpls.tmpls.get(TMPL_GROUP_BY)
				.replace("${"+DEFAULT_GROUP_BY_VAR+"}", "${"+groupByVarname+"}"));
		if(pagequery){
			if(DT_MYSQL.equals(sqltype)){
				conditionCodes.add(Tmpls.tmpls.get(TMPL_LIMIT));
			}
		}
		StringBuffer buffer = new StringBuffer();
		if(!importLines.isEmpty()){
			buffer.append(Joiner.on("\n").join(importLines));
		}
		if(!selectFrom.isEmpty()) {
			buffer.append(String.format("where_buffer.append(\"%s \");\n",selectFrom));
		}
		String script=buffer.append(Tmpls.tmpls.get(TMPL_BEFORE_COND))
				.append(extractReferenceVariables(Joiner.on("\n").join(conditionCodes)))
				.append(Tmpls.tmpls.get(TMPL_AFTER_COND)).toString();
		SimpleLog.log(debuglog,script);
		SimpleLog.log(debuglog,"referenceVariables: {}",Iterables.toString(referenceVariables));
		
		return script;
	}
	/**
	 * 将字符串中的${varname}格式的变量引用名从字符串中摘出参与运算,
	 * 并生成引用变量名集合保存到{@link #referenceVariables} 
	 * @param input
	 * @return 引用变量名集合
	 */
	private String extractReferenceVariables(String input){
		this.referenceVariables = Sets.newHashSet();
		if(!isNullOrEmpty(input)){
			Pattern pattern = Pattern.compile("\\$\\{(\\w+)\\}");
			Matcher matcher = pattern.matcher(input);
			 while (matcher.find()) {
				 referenceVariables.add(matcher.group(1));
			 }
			
			 return replaceVar(input);
		}
		return input;
	}
	
	/**
	 * 通过正则表达式匹配将字符串中的${varname}格式的变量引用名从字符串中摘出参与运算,
	 * @param input
	 * @return 替换后的字符串
	 */
	private String replaceVar(String input){
		/** 
		 * 支持 (?<!pattern) 负向后行断言的正则表达式，用于提取一个双引号开头和结尾的正则表达式
		 * 参见 https://www.runoob.com/w3cnote/reg-lookahead-lookbehind.html 
		 */
		Pattern p1= Pattern.compile("(?<!\\\\)\".*(?<!\\\\)\"");
		Matcher m1 = p1.matcher(input); 
		StringBuffer sb = new StringBuffer();
		while(m1.find()){
			String str = m1.group(0)
					.replaceAll("op\\s*\\(\\s*\\\\\"(\\w+)\\\\\"\\s*\\)", "\"+op(\"$1\")+\"")
					.replaceAll("op\\s*\\(\\s*\\$\\{(\\w+)}\\s*\\)", "\"+op(\"$1\")+\"")
					.replaceAll("\\$\\{(\\w+)}", "\"+$1+\"");
			try {
				m1.appendReplacement(sb, str);	
			} catch (RuntimeException e) {
				/** str 中有$符号时会抛出异常,原样替换 */
				m1.appendReplacement(sb, "$0");
			}
		}
		m1.appendTail(sb);
		return sb.toString().replaceAll("\\$\\{(\\w+)\\}", "$1");
	}
	/**
	 * 从{@link EnableWhereHelper}的{@link EnableWhereHelper#varTypeKeys()}和{@link EnableWhereHelper#varTypeValues()}读取数据
	 * 生成字段名对应的类型映射{@link #varTypes}
	 * @param annot
	 */
	private void buildVarTypes(EnableWhereHelper annot){
		String[] varnames = annot.varTypeKeys();
		Class<?>[] vartypes = annot.varTypeValues();
		/** 数组长度必须一样 */
		checkArgument(varnames.length == vartypes.length,
				"INVALID variable type defined by EnableWhereHelper,array length of varTypeKeys must equal with varTypeValues");
		this.varTypes = Maps.newHashMap();
		for(int i=0;i<varnames.length;++i){
			checkArgument(!isNullOrEmpty(varnames[i]),"varname must not be empty");
			varTypes.put(varnames[i], vartypes[i]);
		}
	}
	/**
	 * 根据指定的条件生成{@link WhereHelper}实例
	 * @return WhereHelper 实例
	 */
	public WhereHelper build() {
		return new WhereHelper(this);
	}

	/**
	 * 检查ORDER BY 字段的合法性,不合法则抛出异常
	 * @param input
	 * @return input always
	 */
	private static String validOrderBy(String input){
		input = nullToEmpty(input).trim();
		checkArgument(!isNullOrEmpty(input) && Pattern.compile("((^|,)\\s*('\\w+'|\\w+)(?: +(ASC|DESC))?)*",
				Pattern.CASE_INSENSITIVE).matcher(input).matches()	,"INVALID ORDER BY COLUMN %s",input);
		return input;
	}

	/**
	 * 检查逻辑操作符的合法性
	 * @param input
	 * @return input always
	 */
	private static String validLogicOperator(String input){
		input = nullToEmpty(input).trim();
		checkArgument(!isNullOrEmpty(input) && Pattern.compile("AND|OR",Pattern.CASE_INSENSITIVE).matcher(input).matches()
				," INVALID logic operator [%s],'AND' or 'OR' required",input);
		return input;
	}

	/**
	 * 加载指定的bsh脚本模板资源
	 * @param tmpl
	 * @return bsh脚本模板
	 */
	private static String loadTemplate(String tmpl){
		URL url = checkNotNull(WhereHelper.class.getResource(tmpl),"not found template %s", tmpl);
		try {
			return Resources.toString(url, Charsets.UTF_8);
		} catch (IOException e) {
			throw new RuntimeException(e);
		} 
	}
	/**
	 * 加载所有需要的bsh脚本模板数据
	 * @return ${模板名}--${脚本模板数据}的映射
	 */
	private static ImmutableMap<String, String> loadAllTemplates(){
		// 加载所有模板
		return  Maps.toMap(Sets.newHashSet(TMPL_EXP,TMPL_EQUAL,TMPL_EQUAL_IF,TMPL_IF_ELSE,TMPL_GROUP_BY,TMPL_ORDER_BY,TMPL_LIMIT,TMPL_BEFORE_COND,TMPL_AFTER_COND), 
				new Function<String, String>() {
					@Override
					public String apply(String input) {
						return loadTemplate("bsh_" + input);
					}
				});
	}
}